package com.hzw.saas.service.rss.parse;

import java.util.ArrayList;
import java.util.List;

import com.hzw.saas.api.rss.bo.JournalArticleBO;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RSSParser {

    public static List<JournalArticleBO> parse(String content) throws Exception {
        Document document = DocumentHelper.parseText(content);
        if (null == document) {
            return null;
        }
        Element rootElement = document.getRootElement();
        String rootName = rootElement.getQName().getName();
        List<Element> items = null;
        log.debug("rss root: {}", rootName);
        // RS 1.0
        if ("rdf".equalsIgnoreCase(rootName)) {
            items = document.getRootElement().elements("item");
        }
        // RS 2.0
        else if ("rss".equalsIgnoreCase(rootName)) {
            items = document.getRootElement().element("channel").elements("item");
        }
        // TODO 添加实现类
        else if ("feed".equalsIgnoreCase(rootName)) {
            items = document.getRootElement().elements("entry");
        }
        else {
            return null;
        }
        log.info("parse items: {}", items.size());
        ArrayList<JournalArticleBO> journalArticleBOS = new ArrayList<>();
        for(Element item : items){
            JournalArticleBO journalArticleBO = new JournalArticleBO();
            //标题
            journalArticleBO.setTitle(findTagText(item, "title"));
            //链接
            journalArticleBO.setLinkUrl(findTagText(item, "origLink", "link"));
            //description
            journalArticleBO.setDescription(updateDesc(findTagText(item, "description", "encoded", "content")));
            //作者
            journalArticleBO.setAuthor(trimArray(findTagText(item, "author", "creator"), ","));
            //subject
            journalArticleBO.setSubject(findTagText(item, "subject", "section"));
            //发布日期
            String pubDateStr = StrUtil.subBefore(
                findTagText(item, "publicationDate", "date", "updated"), "T", false);
            if (!StrUtil.isEmpty(pubDateStr)) {
                journalArticleBO.setPubDate(DateUtil.parse(pubDateStr, "yyyy-MM-dd"));
            }
            // 唯一标识
            String identifier = findDOI(item, journalArticleBO.getDescription());
            journalArticleBO.setIdentifier(identifier);
            //image_title
            journalArticleBO.setImage_title(findImageTitle(journalArticleBO.getDescription()));
            journalArticleBOS.add(journalArticleBO);
        }
        return journalArticleBOS;
    }

    /**
     * 从一个element中按次序找到有内容的text
     * @param item
     * @param tags
     * @return
     */
    private static String findTagText(Element item, String... tags) {
        for (String tag : tags) {
            String text = item.elementText(tag);
            if (!StrUtil.isEmpty(text)) {
                return text.trim();
            }
        }
        return null;
    }

    /**
     * 将一串带分隔符的字符串去掉分隔符前后的空格
     * @param text
     * @param delimiter
     * @return
     */
    public static String trimArray(String text, String delimiter) {
        if (StrUtil.isEmpty(text)) {
            return "";
        }
        String[] words = text.split(delimiter);
        StrUtil.trim(words);
        StringBuilder builder = new StringBuilder(words[0]);
        for (int i = 1; i < words.length; i++) {
            builder.append(delimiter).append(words[i]);
        }
        return builder.toString();
    }

    /**
     * 找到文章DOI
     * @param item
     * @param description
     * @return
     */
    private static String findDOI(Element item, String description) {
        String doi = findTagText(item,"prism:doi", "id");
        // 优先使用DOI
        if (!StrUtil.isEmpty(doi)) {
            return doi;
        }
        String identifier = item.elementText("identifier");
        // 其次使用identifier（去掉可能的前缀）
        if (!StrUtil.isEmpty(identifier)) {
            if (StrUtil.startWith(identifier, "10.")) {
                return identifier.trim();
            } else {
                // 去掉可能的前缀
                return "10." + StrUtil.subAfter(identifier,"10.",false).trim();
            }
        }
        // 再次从description中查找, 格式为 <b>DOI</b>: 10.10XX/XXXXXXXXX,
        if (!StrUtil.isEmpty(description)) {
            String doiSub = StrUtil.subBetween(description, "<b>DOI</b>:", ",");
            if (!StrUtil.isEmpty(doiSub)) {
                return doiSub.trim();
            }
        }
        return "";
    }

    /**
     * 文章摘要(暂时处理)
     * 图片相对路径修复
     * @param description
     * @return
     */
    public static String updateDesc(String description) {
        return StrUtil.replace(description, "/services/images/RSCpubs.", "https://pubs.rsc.org/services/images/RSCpubs.");
    }

    /**
     * 文章摘要处理，提取description中第一张图片
     * @param description
     * @return
     */
    private static String findImageTitle(String description){
        if (StrUtil.isNotBlank(description)){
            String s = StrUtil.subBetween(description, "<img", "/>");
            String substring = StrUtil.subBetween(s, "src=\"", "\"");
            return substring;
        }
        return "";
    }
}
